#!/bin/bash
#################################################################
#
# https://gitee.com/xinghuowangluo/lan_tools/openvpn-install.sh 
# openvpn 安装配置脚本
# author linghuo
#################################################################
path=$(cd $(dirname $0);pwd)
ca_easy_path="${path}/ca-easy-rsa"
easy_path="${path}/easy-rsa"
echo "  OpenVPN提供了两种登陆认证方法：用户名/密码和SSL证书认证，这里使用ssl证书认证方式。"
function crt_read(){
	echo "  服务器SSL数字证书和客户端单位数字证书的格式遵循 X.509 标准"
	echo "  X.509证书:"
	echo "  	X.509标准是密码学里公钥证书的格式标准,X.509证书含有公钥和标识（主机名、组织或个人），并由证书颁发机构（CA）签名（或自签名）。"
	echo "  	对于一份经由可信的证书签发机构签名（或者可以通过其它方式验证）的证书，证书的拥有者就可以用证书及相应的私钥来创建安全的通信，以及对文档进行数字签名。"
	echo "  	x509证书一般会用到三类文，key，csr，crt。"
	echo "  	Key:是私用密钥。csr是证书请求文件，用于申请证书,crt是CA认证后的证书文"
	echo 
	echo "  CA:"
	echo "  	CA是证书的签发机构，它是公钥基础设施（Public Key Infrastructure，PKI）的核心。CA是负责签发证书、认证证书、管理已颁发证书的机关。 "
	echo "  	CA 拥有一个证书（内含公钥和私钥）。任何人都可以得到 CA 的证书（含公钥），用以验证它所签发的证书。"
	echo ""
	echo "  证书申请流程:"
	echo "  	如果用户想得到一份属于自己的证书，他先生成自己的私钥 key 再由key 生成csr (KEY --> CSR) 最后,把csr文件提交给 CA 申请证书。"
	echo ""
	echo "证书制作工具:"
	echo "	openvpn 使用easy-rsa，制作证书。 "
	echo "	easy-rsa 参考文档：https://wiki.archlinux.org/title/Easy-RSA"
	echo ""
	echo "此脚本会在当前目录构建CA工具,并以 ca-easy-rsa 命名,配置完后便于把ca迁移到单独的服务器,ca和vpn服务分开部署可以增加服务器的安全。"
	echo ""
	echo ""
	echo ""
}
echo "  安装openvpn 分两步"
echo "		一,配置ssl证书"
echo "		二,配置openvpn"
echo "		三,生成客户端配置脚本"
echo ""

#判断操作系统是否支持
if grep -qs "ubuntu" /etc/os-release; then
	os="ubuntu"
	os_version=$(grep 'VERSION_ID' /etc/os-release | cut -d '"' -f 2 | tr -d '.')
	group_name="nogroup"
else
	echo "此安装脚本目前只支持ubuntu 18.04以上的版本"
	exit
fi
if [[ "$os" == "ubuntu" && "$os_version" -lt 1804 ]]; then
	echo "此安装脚本目前只支持ubuntu 18.04以上的版本.您的版本太旧不支持。"
	exit
fi

 
echo "

###################################################################################
#                                                                                 #
#                                一,配置ssl证书                                   #
#                                                                                 #
###################################################################################
"
read -p "是否配置证书: [y]:"  crtstatus
[[ -z $crtstatus ]] && crtstatus='y'
if [[ $crtstatus == 'y' ]];then
	#安装openvpn、easy-rsa
	if [[   ! -e /etc/openvpn/server/server.conf ]]; then
		echo "开始安装 openvpn 和 easy-rsa ...."
		sudo apt-get update
		sudo apt install openssl libssl-dev lzop easy-rsa openvpn -y
	fi
	echo ""
	echo ""
	echo ""

	crt_read
	echo ""
	echo ""
	echo ""
	echo ""
	read -p "开始构建CA和PKI基础架构复制一份easy-rsa工具命名为'ca-easy-rsa':[y] :" status
	[[ -z $status ]] && status="y"
	if [[ $status == "y" ]];then
		if [[ -d /usr/share/easy-rsa/ ]];then
			cp -a /usr/share/easy-rsa/ ${ca_easy_path}
		else 
			echo "easy-rsa 未安装"
			exit
		fi
		cd ${ca_easy_path}
		#设置CA变量
		echo "设置CA变量"
		echo ""
		read -p "输入国家代码[CN]:" country
		read -p "输入省[HENAN]: " province
		read -p "输入城市[PUYANG]: " city
		read -p "输入组织代码[LINGHUO]: " org
		read -p "输入邮箱[linghuo@qq.com]: " email
		read -p "输入社区[LH]: " ou
		[[ -z "$country" ]] && country="CN"
		[[ -z "$province" ]] && province="HENAN"
		[[ -z "$city" ]] && city="PUYANG"
		[[ -z "$org" ]] && org="LINGHUO"
		[[ -z "$email" ]] && email="linghuo@qq.com"
		[[ -z "$ou" ]] && ou="LH"

		echo "
		set_var EASYRSA_REQ_COUNTRY     \"$country\"
		set_var EASYRSA_REQ_PROVINCE    \"$province\"
		set_var EASYRSA_REQ_CITY        \"$city\"
		set_var EASYRSA_REQ_ORG         \"$org\"
		set_var EASYRSA_REQ_EMAIL       \"$email\"
		set_var EASYRSA_REQ_OU          \"$ou\" ">${ca_easy_path}/vars

		echo ""
		echo "创建公钥基础结构"
		./easyrsa init-pki
		echo ""
		read -p "创建ca.crt 和 ca.key 是否设置密码[n]:" pass
		if [[ -z $pass ]];then
			./easyrsa build-ca nopass
		else 
			./easyrsa build-ca
		fi
	fi


	read -p "创建openvpn服务器证书及密钥，在当前目录复制一份easy-rsa命名为'easy-rsa':[y]:" server_status
	[[ -z $server_status ]] && server_status="y"
	if [[ $server_status == "y" ]];then
		cp -a /usr/share/easy-rsa $easy_path
		cd $easy_path
		./easyrsa init-pki
		read -p "为openvpn 服务器生成一个证书请求文件req"
		./easyrsa gen-req server nopass
		echo ""
		read -p "将证书请求文件req复制到CA目录制作证书"
		cp -av $easy_path/pki/reqs/server.req $ca_easy_path/
		cd $ca_easy_path
		#导入请求文件  然后通过使用sign-req选项运行easyrsa脚本，然后签署请求类型和公用名称来sign-req 请求 。
		# 请求类型可以是client或server ，因此对于OpenVPN服务器的证书请求，请确保使用server请求类型： 
		./easyrsa import-req  server.req server
		echo "签名生成crt证书 系统会要求您验证请求是否来自可信来源。 ENTER yes然后按ENTER确认："
		./easyrsa sign-req server server
		echo "复制server.crt,ca.crt和key 到openvpn配置目录"
		sudo cp -av $ca_easy_path/pki/ca.crt /etc/openvpn/
		sudo cp -av $ca_easy_path/pki/issued/server.crt /etc/openvpn/
		sudo cp -av $easy_path/pki/private/server.key /etc/openvpn/
		echo ""


		read -p "进入easy-rsa创建一个强大的Diffie-Hellman密钥，以便在密钥交换期间使用"
		cd $easy_path
		./easyrsa gen-dh
		echo ""
		read -p "使用openvpn 生成一个HMAC签名以加强服务器的TLS完整性验证功能："
		openvpn --genkey --secret ta.key
		echo ""
		read -p "这两个新文件复制到/etc/openvpn/目录中："
		sudo cp -av $easy_path/pki/dh.pem /etc/openvpn/
		sudo cp -av $easy_path/ta.key /etc/openvpn/
	fi
fi

echo "  安装openvpn 分两步"
echo "		一,配置ssl证书"
echo "		二,配置openvpn"
echo "		三,生成客户端配置脚本"
echo ""
echo "
###################################################################################
#                                                                                 #
#                              二，配置openvpn                                    #
#                                                                                 #
###################################################################################

"
read -p "配置openvpn config 文件[y]:" pconfstatus
[[ -z $pconfstatus ]] && pconfstatus='y'
if [[ $pconfstatus == 'y' ]];then
	echo "将示例OpenVPN配置文件复制到配置目录中进行修改示例文件内有注释,可以参考学习"
	read -p "开始配置"
	sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
	sudo gzip -d /etc/openvpn/server.conf.gz
	configfile="/etc/openvpn/server.conf"
	echo "配置 tls-auth指令来查找HMAC部分 在该行下方，添加key-direction参数，设置为“0”："
	echo "配置 cipher AES-256-CBC #AES-256-CBC密码提供了良好的加密级别，并得到很好的支持"
	echo "添加一个auth指令来选择HMAC消息摘要算法 auth SHA256"
	echo "配置Diffie-Hellman密钥的文件：dh dh.pem"
	echo "配置 user nobody"
	echo "配置 group nogroup"
	echo ""
	read -p "配置推送DHCP[y]:" dchpan
	[[ -z $dchpan ]] && dchpan='y'
	if [[ $dchpan == 'y' ]];then 
		sudo echo ""|sudo tee -a $configfile
		sudo echo "push \"redirect-gateway def1 bypass-dhcp\"" |sudo tee -a $configfile
		echo "配置DHCP"
		echo ""
	fi
	read -p "配置推送DNS[y]:" dnsan
	[[ -z $dnsan ]]  && dnsan='y'
	if [[ $dnsan == 'y' ]];then 
		read -p "DNS1 [208.67.222.222]:" DNS1
		read -p "DNS2: [208.67.222.220]:" DNS2
		[[ -z $DNS1 ]] && DNS1="208.67.222.222"
		[[ -z $DNS2 ]] && DNS2="208.67.220.220"
		
		sudo echo "push \"dhcp-option DNS $DNS1\"" |sudo tee -a $configfile
		sudo echo "push \"dhcp-option DNS $DNS2\"" |sudo tee -a $configfile
		echo "配置DNS"
	fi
	sudo sed  -i '/^tls-auth/a\key-direction 0' $configfile
	sudo sed  -i '/^cipher AES-256-CBC/a\auth SHA256' $configfile
	sudo sed  -i 's/^dh\s*dh2048.pem/dh dh.pem/g' $configfile
	sudo sed  -i 's/^;user nobody/user nobody/g' $configfile
	sudo sed  -i 's/^;group nogroup/group nogroup/g' $configfile
	echo ""
	read -p "配置协议[udp]:" tcpan
	[[ -z $tcpan ]] && tcpan='udp'
	if [[ $tcpan == 'tcp' ]];then
		sudo sed  -i 's/^proto\s*udp/proto tcp/g' $configfile
		sudo sed  -i 's/^explicit-exit-notify\s*1/explicit-exit-notify 0/g' $configfile
		echo "配置ＴＣＰ协议需要　explicit-exit-notify 的值设置为0"
	fi
fi



read -p "配置防火啬及foward转发[y]:" firestatus
[[ -z $firestatus ]] && firestatus='y'
if [[ $firestatus == 'y' ]];then
	sudo sed -i 's/^#net.ipv4.ip_forward/net.ipv4.ip_forward/g' /etc/sysctl.conf
	sudo sysctl -p

	#获取出口网卡
	netdev=$(ip route | grep default|head -1|awk '{print $5}')
	echo "iptable 增加 POSTROUTING"
	sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/8 -o $netdev -j MASQUERADE
	echo "如果连不上vpn请检查防火墙"
	echo ""
fi
echo ""
read -p "服务端配置已完成,是否启动vpn[y]:" vpnstatus
[[ -z $vpnstatus ]] && vpnstatus='y'
if [[ $vpnstatus == 'y' ]];then
	#sudo /etc/init.d/openvpn start
	sudo systemctl enable openvpn.service
	sudo systemctl start openvpn.service
fi

echo "  安装openvpn 分两步"
echo "		一,配置ssl证书"
echo "		二,配置openvpn"
echo "		三,生成客户端配置脚本"
echo ""
echo "
###################################################################################
#                                                                                 #
#                            三,生成客户端配置脚本                                #
#                                                                                 #
###################################################################################
"
read -p  "最后一步,生成客户端配置脚本 [y]" clientstatus
[[ -z $clientstatus ]] && clientstatus='y'
if [[ $clientstatus == 'y' ]];then
	echo "生成客户端证书"
	echo "生成客户端配置脚本文件 make_config.sh"
	echo "客户端配置文件,创建client-configs目录存放客户端配置的文件"
	cd $path

	cfpath=$path/client-configs
	basefile=$cfpath/base.conf
	mkdir -vp $cfpath/{files,keys}

	cp -av  /usr/share/doc/openvpn/examples/sample-config-files/client.conf $basefile
	read -p "配置client协议[udp]:" tcpan
	[[ -z $tcpan ]] && tcpan='udp'
	if [[ $tcpan == 'tcp' ]];then
		sudo sed  -i 's/^proto\s*udp/proto tcp/g' $basefile
		sudo sed  -i 's/^explicit-exit-notify\s*1/explicit-exit-notify 0/g' $basefile
	fi
	read -p "输入服务器ＩＰ：[127.0.0.1]:" SERVER_IP
	[[ -z $SERVER_IP ]] && SERVER_IP="127.0.0.1"
	sudo sed -i 's/my-server-1/'$SERVER_IP'/g' $basefile
	sudo sed  -i 's/^;user nobody/user nobody/g' $basefile
	sudo sed  -i 's/^;group nogroup/group nogroup/g' $basefile
	sudo sed  -i 's/^ca\s*ca.crt/;ca ca.crt/g' $basefile
	sudo sed  -i 's/^cert\s*client.crt/;cert client.crt/g' $basefile
	sudo sed  -i 's/^key\s*client.key/;key client.key/g' $basefile
	sudo sed  -i '/^tls-auth/a\key-direction 1' $basefile
	sudo sed  -i '/^cipher AES-256-CBC/a\auth SHA256' $basefile

	sudo cp -av $easy_path/ta.key $cfpath/keys/
	sudo cp -av $ca_easy_path/pki/ca.crt $cfpath/keys/
	echo ""
	echo "生成客户端配置脚本文件"
	echo "
	#!/bin/bash
	#####################################
	# 第一个参数为客户端名字
	# 例:./make_config.sh linghuo
	#####################################

	echo \"生成客户端配置脚本文件 \"
	echo \"客户端配置文件,创建client-configs目录存放客户端配置的文件\"
	echo \"进入到openvpn　easy-rsa 目录　生成证书请求文件和key\"
	echo \"ubuntu 需要安装apt install　resolvconf;　，/etc/openvpn/update-resolv-conf这个脚本会用到。\"
	path=\$(cd \$(dirname \$0);pwd)
	cfpath=\$path/client-configs
	BASE_CONFIG=\$cfpath/base.conf
	KEY_DIR=\${cfpath}/keys
	OUTPUT_DIR=\${cfpath}/files
	ca_easy_path=\"\${path}/ca-easy-rsa\"
	mkdir -vp \$cfpath/{files,keys}

	read -p \"生成证书请求文件和key[用户名]:\" username
	if [[ -z \$username ]];then
	    echo \"没有输入用户名\"
	    exit
	fi

    read -p \"是否设置密码 [yes]:\" pass
    if [[ -z $pass ]];then
            pass=''
    else
            pass='nopass'
    fi

	cd \$ca_easy_path
	./easyrsa gen-req \$username $pass
	./easyrsa import-req pki/reqs/\${username}.req \${username}
	./easyrsa sign-req client \$username
	echo \"\"
	echo \"\"
	echo \"复制key,crt 到client-configs/keys目录\"
	cp -av pki/issued/\${username}.crt \$KEY_DIR/
	cp -av pki/private/\${username}.key \$KEY_DIR/
	read -p \"您使用的操作系统是windows|linux [windows]:\" osstatus
	[[ -z \$osstatus ]] && osstatus='windows'
	if [[ \$osstatus == 'linux' ]];then
	    filetype='conf'
	    lcf=\"script-security 2\\nup /etc/openvpn/update-resolv-conf\\ndown /etc/openvpn/update-resolv-conf\\n
	 \"
	 echo \"请检查linux客户端口是否安装了resolvconf　在脚本update-resolv-conf中需要用到。\"
	else
	    filetype=ovpn
	fi

	echo \"\"
	cat \${BASE_CONFIG} \\
	    <(echo -e \$lcf) \\
	    <(echo -e '<ca>') \\
	    \${KEY_DIR}/ca.crt \\
	    <(echo -e '</ca>\n<cert>') \\
	    \${KEY_DIR}/\${username}.crt \\
	    <(echo -e '</cert>\n<key>') \\
	    \${KEY_DIR}/\${username}.key \\
	    <(echo -e '</key>\n<tls-auth>') \\
	    \${KEY_DIR}/ta.key \\
	    <(echo -e '</tls-auth>') \\
	    > \${OUTPUT_DIR}/\${username}.\$filetype
	echo \"\"
	echo \"配置文件已生成，请下载 \${OUTPUT_DIR}/\${username}.\$filetype\"
	">make_config.sh
	chmod a+x make_config.sh
	echo "生成客户端配置文件，请执行：./make_config"
fi